﻿Imports System.IO.Compression
Imports System.Runtime.CompilerServices
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
''' <summary>
''' This module provide Extension for the DataTable and DataSet
''' </summary>
''' <remarks></remarks>
Public Module DataExtension
    ''' <summary>
    ''' Transform a DataTable to a GZIPed byte array
    ''' </summary>
    ''' <param name="dt"></param>
    ''' <returns>Return a Gzip byte array </returns>
    ''' <remarks>If an error occur, no exception is thrown but the Byte Array will be null</remarks>
    <Extension()>
    Public Function PushDataTable(ByVal dt As DataTable) As Byte()
        Dim data As Byte()
        Try
            Dim memStream As New MemoryStream()
            Using zipStream As New GZipStream(memStream, CompressionMode.Compress)
                dt.WriteXml(zipStream, XmlWriteMode.WriteSchema)
                zipStream.Close()
            End Using
            data = memStream.ToArray
            memStream.Close()
        Catch
            data = Nothing
        End Try
        Return data
    End Function
    ''' <summary>
    ''' Transform a GZiped byte array to a DataTable
    ''' </summary>
    ''' <param name="data"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the DataTable will be null</remarks>
    <Extension()>
    Public Function PullDataTable(ByVal dt As DataTable, ByVal data As Byte()) As DataTable
        Try
            Dim memStream As New MemoryStream(data)
            Using unzipStream As New System.IO.Compression.GZipStream(memStream, CompressionMode.Decompress)
                dt.ReadXml(unzipStream)
                unzipStream.Close()
                memStream.Close()
            End Using
            memStream.Dispose()
        Catch ex As Exception
            dt = Nothing
        End Try
        Return dt
    End Function
    ''' <summary>
    ''' Transform a DataSet to a GZIPed byte array
    ''' </summary>
    ''' <param name="ds"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the Byte Array will be null</remarks>
    <Extension()>
    Public Function PushDataSet(ByVal ds As DataSet) As Byte()
        Dim data As Byte()
        Try
            Dim memStream As New MemoryStream()
            Using zipStream As New GZipStream(memStream, CompressionMode.Compress)
                ds.WriteXml(zipStream, XmlWriteMode.WriteSchema)
                zipStream.Close()
            End Using
            data = memStream.ToArray()
            memStream.Close()
        Catch
            data = Nothing
        End Try
        Return data
    End Function
    ''' <summary>
    ''' Transform a GZiped byte array to a DataSet
    ''' </summary>
    ''' <param name="data"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the Dataset will be null</remarks>
    <Extension()>
    Public Function PullDataSet(ByVal ds As DataSet, ByVal data As Byte()) As DataSet
        Try
            Using memStream As New MemoryStream(data)
                Dim unzipStream As New GZipStream(memStream, CompressionMode.Decompress)
                ds.ReadXml(unzipStream, XmlReadMode.ReadSchema)
                unzipStream.Close()
                memStream.Close()
            End Using
        Catch ex As Exception
            ds = Nothing
        End Try
        Return ds
    End Function
    ''' <summary>
    ''' Transform a DataTable to a GZIPed byte array
    ''' </summary>
    ''' <param name="dt"></param>
    ''' <returns>Return a Gzip byte array </returns>
    ''' <remarks>If an error occur, no exception is thrown but the Byte Array will be null</remarks>
    <Extension()>
    Public Function SerializeDataTable(ByVal dt As DataTable) As Byte()
        Dim data As Byte()
        Try
            dt.RemotingFormat = SerializationFormat.Binary
            Dim memStream As New MemoryStream()
            Dim bformat As BinaryFormatter = New BinaryFormatter()
            Using zipStream As New GZipStream(memStream, CompressionMode.Compress)
                bformat.Serialize(zipStream, dt)
                zipStream.Close()
            End Using
            data = memStream.ToArray
            memStream.Close()
        Catch ex As Exception
            data = Nothing
        End Try
        Return data
    End Function
    ''' <summary>
    ''' Transform a GZiped byte array to a DataTable
    ''' </summary>
    ''' <param name="data"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the DataTable will be null</remarks>
    <Extension()>
    Public Function DeSerializeDataTable(ByVal dt As DataTable, ByVal data As Byte()) As DataTable
        Try
            Dim memStream As New MemoryStream(data)
            Dim bformat As BinaryFormatter = New BinaryFormatter()
            Using unzipStream As New System.IO.Compression.GZipStream(memStream, CompressionMode.Decompress)
                dt = CType(bformat.Deserialize(unzipStream), DataTable)
                unzipStream.Close()
                memStream.Close()
            End Using
            memStream.Dispose()
        Catch ex As Exception
            dt = Nothing
        End Try
        Return dt
    End Function
    ''' <summary>
    ''' Transform a DataSet to a GZIPed byte array
    ''' </summary>
    ''' <param name="ds"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the Byte Array will be null</remarks>
    <Extension()>
    Public Function SerializeDataSet(ByVal ds As DataSet) As Byte()
        Dim data As Byte()
        Try
            ds.RemotingFormat = SerializationFormat.Binary
            Dim memStream As New MemoryStream()
            Dim bformat As BinaryFormatter = New BinaryFormatter()
            Using zipStream As New GZipStream(memStream, CompressionMode.Compress)
                bformat.Serialize(zipStream, ds)
                zipStream.Close()
            End Using
            data = memStream.ToArray()
            memStream.Close()
        Catch ex As Exception
            data = Nothing
        End Try
        Return data
    End Function
    ''' <summary>
    ''' Transform a GZiped byte array to a DataSet
    ''' </summary>
    ''' <param name="data"></param>
    ''' <returns></returns>
    ''' <remarks>If an error occur, no exception is thrown but the Dataset will be null</remarks>
    <Extension()>
    Public Function DeSerializeDataSet(ByVal ds As DataSet, ByVal data As Byte()) As DataSet
        Try
            Using memStream As New MemoryStream(data)
                Dim bformat As BinaryFormatter = New BinaryFormatter()
                Dim unzipStream As New GZipStream(memStream, CompressionMode.Decompress)
                ds = CType(bformat.Deserialize(unzipStream), DataSet)
                unzipStream.Close()
                memStream.Close()
            End Using
        Catch ex As Exception
            ds = Nothing
        End Try
        Return ds
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="datarow"></param>
    ''' <param name="columnName">ColumName</param>
    ''' <param name="currentValue">Current Value in the Column</param>
    ''' <param name="originalValue">Value before the change</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Extension()>
    Public Function IsColumnChanged(ByVal datarow As DataRow, ByVal columnName As String, Optional ByRef currentValue As Object = Nothing, Optional ByRef originalValue As Object = Nothing) As Boolean
        Dim hasChanged As Boolean = False
        originalValue = Nothing
        If datarow.HasVersion(DataRowVersion.Current) AndAlso datarow.HasVersion(DataRowVersion.Original) Then
            If Not datarow(columnName, DataRowVersion.Current).Equals(datarow(columnName, DataRowVersion.Original)) Then
                hasChanged = True
                originalValue = datarow(columnName, DataRowVersion.Original)
                currentValue = datarow(columnName, DataRowVersion.Current)
            End If
        ElseIf datarow.HasVersion(DataRowVersion.Current) AndAlso datarow.HasVersion(DataRowVersion.Original) = False Then
            If Not IsDBNull(datarow(columnName, DataRowVersion.Current)) Then
                hasChanged = True
                currentValue = datarow(columnName, DataRowVersion.Current)
            End If
        ElseIf datarow.HasVersion(DataRowVersion.Current) AndAlso datarow.HasVersion(DataRowVersion.Proposed) = False Then
            If Not IsDBNull(datarow(columnName, DataRowVersion.Current)) Then
                hasChanged = True
                currentValue = datarow(columnName, DataRowVersion.Current)
            End If
        End If
        Return hasChanged
    End Function
End Module
